package com.cdht.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.cdht.dto.ResponseDecryptResult;
import com.cdht.dto.ResquestEncryptResult;
import com.cdht.exception.DataException;

public class DataUtil {
    
    private  static final Logger logger = LoggerFactory.getLogger(DataUtil.class);
    
    
    /**
     * 加密数据
     * @param data
     * @param publicKey 
     * @param privateKey
     * @return
     */
    public static ResquestEncryptResult encrypt(String data,String publicKey,String privateKey,boolean createSign)  {
      
       try {
           //验证数据是否完成
           if(StringUtils.isEmpty(data)) {
               DataException.throwException("加密数据内容不能为空");
           }
           if(StringUtils.isEmpty(publicKey)) {
               DataException.throwException("publicKey不能为空");
           }
           if(StringUtils.isEmpty(privateKey)) {
               DataException.throwException("privateKey不能为空");
           }
            //使用aes生成key
           String key  =  AesUtils.createKey();
           //使用key加密数据
           String encryptData = AesUtils.encode(key, data);
           //使用公钥加密数据加密key
           //加密后的key
           String encryptKey = RSAUtil.encrypt(key, RSAUtil.getPublicKey(publicKey));
           //生成验签
           String sign = null ;
           if(createSign) {
               sign = RSAUtil.sign(key,  RSAUtil.getPrivateKey(privateKey));
           }
           return new ResquestEncryptResult(ResquestEncryptResult.SUCCESS, encryptData, encryptKey, sign, "加密成功");
       }catch (DataException e) {
           logger.info("数据加密失败:"+e.getMessage());
           return new ResquestEncryptResult(ResquestEncryptResult.FAIL, null, null, null, "加密失败,"+e.getMessage());
       } catch (Exception e) {
           logger.info("数据加密失败:"+e.getMessage());
           return new ResquestEncryptResult(ResquestEncryptResult.FAIL, null, null, null, "加密失败"); 
       }        
    }
    
    /**
     * 默认需要签名
     * @param aSendData
     * @param aPublicKey
     * @param aPrivateKey
     * @return
     */
    public static ResquestEncryptResult encrypt(String data, String publicKey, String privateKey) {
        return encrypt(data, publicKey, privateKey,true);
    } 
    
    /**
     * 解密数据
     * @param data
     * @param publicKey 
     * @param privateKey
     * @return
     */
    public static ResponseDecryptResult decrypt(ResquestEncryptResult resquestEncryptResult,String publicKey,String privateKey,boolean verifySign)  {
      try {
          if(resquestEncryptResult == null) {
              DataException.throwException("解密对象不能为空");
          }
          if(StringUtils.isEmpty(resquestEncryptResult.getEncryptData())) {
              DataException.throwException("待解密内容不能为空");
          }
          if(StringUtils.isEmpty(resquestEncryptResult.getEncryptKey())) {
              DataException.throwException("待解密key内容不能为空");
          }
          if(verifySign) {
              if(StringUtils.isEmpty(resquestEncryptResult.getSign())) {
                  DataException.throwException("内容签名不能为空");
              } 
          }
          
          if(StringUtils.isEmpty(publicKey)) {
              DataException.throwException("publicKey不能为空");
          }
          if(StringUtils.isEmpty(privateKey)) {
              DataException.throwException("privateKey不能为空");
          }
          //解密获取加密key
          String  encryptKey = resquestEncryptResult.getEncryptKey();
          String key = RSAUtil.decrypt(encryptKey, RSAUtil.getPrivateKey(privateKey));
          //验签
          if(verifySign) {
              String sign = resquestEncryptResult.getSign();
              boolean verifyResult = RSAUtil.verify(key, RSAUtil.getPublicKey(publicKey), sign);
              if(!verifyResult) {
                 //数据验签失败，数据已被串改
                  DataException.throwException("数据内容被篡改，验签失败");
              }
          }
          //使用key解码数据   
          String encryptData =  resquestEncryptResult.getEncryptData();
          String data = AesUtils.decode(key, encryptData);
          return new ResponseDecryptResult(ResponseDecryptResult.SUCCESS, data,"解密成功");
      }catch (DataException e) {
          logger.info("数据解码失败:"+e.getMessage());
          return new ResponseDecryptResult(ResponseDecryptResult.FAIL, null,"解密失败,"+e.getMessage());
      }  catch (Exception e) {
          logger.error("数据解码失败:"+e.getMessage());
          return new ResponseDecryptResult(ResponseDecryptResult.FAIL, null,"解密失败");
      } 
    }
    
    /**
     *  默认需要验证签名
     * @param aEncryptData
     * @param bPublicKey
     * @param bPrivateKey
     * @return
     */
    public static ResponseDecryptResult decrypt(ResquestEncryptResult resquestEncryptResult, String publicKey,
            String privateKey) {
        return decrypt(resquestEncryptResult, publicKey, privateKey,true);
    }


   
    
    public static void main(String[] args) {
        //过程 我方生成2把公私密码，我方把保存其中一对的公钥和另一个的私钥，将剩下的给对方，
        //数据加密过程使用AES,生成加密结果,对AES加密KEY使用公私秘钥加密解密
        //我方接口响应结果用公钥加密，对方用持有的私钥解密
        //对方请求参数使用公钥加密，我方使用持有私钥解密
       
        
        //A方持有
        String aPrivateKey ="MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKoCdXbauAMP+6ntaPASi6BduzTyr1xK+XH5BdjghN6JP05p7lzyZu1DPQaMITLxs63XAQQ8I6klfHoJnA87/ZpnfvLeQJ1FN11PR4xEzhg2qQgqMzG8OReS3Ob5WPr4DoFt1XWBqK7s86bBBmb8apaZLar4Q155k650uB2Y6SebAgMBAAECgYEAnDIuIcjJj2a73V+WLhub1PbI7NibbLwleiVEzgFZkeufEjgZG6RKFGrWQpG0Xs3aOzlyYaWvTdR3DNiPXR/M2vMdc73A2wlHw1Uie/B55+0oFYZFq+Tpbg3uePErqNCuB0bGFPCQPZ5akysQRvwL2t/RaDiSIxYDERvO3KeJ8AECQQDgrM31q9xTBuznIaUR6moPL1/sjxmMChKV5i1+WK3Aj7MoFWfnShfLg+UfDQ8taAH/Op2qLMkX3BthhwgoIU2bAkEAwbaDat2srqCPk3kcmpZvSO1XbrmzXLw6v6cfHQDWX5WyYNX+KrMEy4S8a/alsodsZjJ8gKw50VJ1B3US9uIuAQJBALLbXiqQ4hiGjtmBAzO79SqZgDeFw8Sj0B/c2aKXXdrJisoCIHETntW47hFGCCsRfWV9eD4c4QlJg9Kj+G5Z9LkCQEl7z/yRHPmdpPl/nw8xdAPJLTqurVDHgs3DOvVIpQnbgrBjXSibgn0l3EhkZ1UDNGbMThiNvN0gF479pXUMNgECQDHZoPO67FgDP0p7XqDA0yLlRiSSgHlmWKZ9en7MKLkFtYMqy7yphmoRXLl8ays0NmMYtMHQsHS/ct692cLanBo=";
        String aPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJzvc7ngh0sJDndGoLPqhIPdzsS1GLAgEW6IzK5WFGu7kLb+VGbBMuvQwluwOdXs539gM/riIbHnHYnmEQ7jzu+A5Ben31VSj6OnhLKVdOACj5hkqkoqSAQCxAUK6D8ht16zznudzagXWbXzriGK+i2KZKsWcg8Dn4U5h7ORAkIwIDAQAB";
        //B方持有
        String bPrivateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAInO9zueCHSwkOd0ags+qEg93OxLUYsCARbojMrlYUa7uQtv5UZsEy69DCW7A51eznf2Az+uIhsecdieYRDuPO74DkF6ffVVKPo6eEspV04AKPmGSqSipIBALEBQroPyG3XrPOe53NqBdZtfOuIYr6LYpkqxZyDwOfhTmHs5ECQjAgMBAAECgYBHrT1MZeMSBnAn4pXxaVKP2JVa1cYA3jcA2k24jlvtNWCGwVloKnhDvBJgYYf8xz3uiSehbInSvyAJwj7MVo2cHVCEBOhhfS8yQeC2A01FoocgWXTKcpa75KOJtskfMX0v7iMt6yUIDLcHt9pmkEbiWxnI0XbtjpSbs8/3n9/lgQJBAM91d270GNEFqcLKemTbpxnu3R80F8lgx4ADydZSSQoURz1U44LrznASEa3W85ptomX3bDpgy82cMuaYneQXcmMCQQCqDYZzPH0G/Yy8euebHV6T4SdTXYHZ1X2uHYZ60dMrxGQaumvxZ7MBpZgiyxxtjy3kbIZJLzXb5Dy6xR/CwlNBAkEAqgx4HGta2CJTN0ausnNVci1X9NbHVJrOjEEOtW13Txq2FjC52DufWD+HXD4gKYoKHpiDjwp+o4eQNXINocQSTwJAPdadRdqBPMGHJCMtheKwOeZufopKZgSUp3RlKtSSjh/kpzOTfT3QgpDNOhnSRKUEc0RjsMlSNJxS2ThFzHUOAQJAe92/2EaKI+J4fwiY7gTL1/P/x0bTkfSJcOfe3S3ANb5Mk6Z7IhWkcXZD8JF/ycTB0BXxf4NIzLcAYgrZc7gmpg==";
        String bPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqAnV22rgDD/up7WjwEougXbs08q9cSvlx+QXY4ITeiT9Oae5c8mbtQz0GjCEy8bOt1wEEPCOpJXx6CZwPO/2aZ37y3kCdRTddT0eMRM4YNqkIKjMxvDkXktzm+Vj6+A6BbdV1gaiu7POmwQZm/GqWmS2q+ENeeZOudLgdmOknmwIDAQAB";
        
        //A传给B信息，B解析信息
        String aSendData = "A传给B信息，B解析信息"; 
        System.out.println("A传给B信息，B解析信息 待加密信息:"+aSendData);
        //A用公钥加密信息，B用私钥解密信息
         ResquestEncryptResult aEncryptData = DataUtil.encrypt(aSendData, aPublicKey, aPrivateKey);
         System.out.println("A传给B信息,加密后的内容:"+aEncryptData);
        //B用私钥解密信息
         ResponseDecryptResult bDecryptData = DataUtil.decrypt(aEncryptData, bPublicKey, bPrivateKey);
         System.out.println("A传给B信息，B解析信息,获取到内容："+bDecryptData);
         
        //B传输给A信息，A解析信息
        String bSendData = "B传输给A信息，A解析信息"; 
        System.out.println("B传输给A信息，A解析信息 待加密信息："+bSendData);
        //B用公钥加密信息，A用私钥解密信息
        ResquestEncryptResult bEncryptData = DataUtil.encrypt(bSendData, bPublicKey, bPrivateKey);
        System.out.println("B传输给A信息，A解析信息:"+aEncryptData);
       //B用私钥解密信息
        ResponseDecryptResult aDecryptData = DataUtil.decrypt(bEncryptData, aPublicKey, aPrivateKey);
        System.out.println("B传输给A信息，A解析信息,获取到内容："+aDecryptData);
    }


    
}
